export default (enforce?: 'pre' | 'post') => {
  return {
    name: 'test',
    enforce

    /** case2
     * 在插件当中根据其它的一些配置来更新整体的config,它return的对象会被合并到整个vite的config中*/
    //只会执行一次
    ,config(userConfig){
      console.log('config');
      // console.log('config:',userConfig)
      /*
        config: {
          plugins: [
            {
              name: 'test',
              enforce: undefined,
              buildStart: [Function: buildStart],
              resolveId: [Function: resolveId],
              config: [Function: config],
              configResolved: [Function: configResolved]
            }
          ],
          resolve: { alias: { '@styles': '/src/styles' } },
          server: {}
        }

      */

      //是一个deep merge
      /*return {
        resolve: {
          alias: {
            '@aaa':'/src/styles'
          }
        }
      }*/

      //如果返回的是一个promise 也会等到promise resolve的结果 才会执行configResolved的逻辑(钩子)
      /*return new Promise(resolve => {
        resolve({
          resolve: {
            alias: {
              '@aaa': '/src/styles'
            }
          }
        });
      });*/

    }

    //所有插件的config执行完之后才会执行
    //不要再在这里取修改配置,这是最终的
    //我们可以在这里从最终的配置中读取一些数据存到我们的本地环境里（闭包中）---> 参看 `11.插件开发のvite-vue3-jsx/index.js` 中 configResolved 的用法
    //只会执行一次
    ,configResolved(config){
      console.log('configResolved config: --- --- --- --- --- ---');
      // console.log('config.resolve:',config.resolve);
      /*
        config.resolve: {
          dedupe: undefined,
          alias: [
            { find: '@styles', replacement: '/src/styles' },
            { find: '@aaa', replacement: '/src/styles' },
            { find: /^[\/]?@vite\/env/, replacement: [Function: replacement] },
            {
              find: /^[\/]?@vite\/client/,
              replacement: [Function: replacement]
            }
          ]
        }
      */
    }

    /** case3 自定义中间件 拦截请求*/
    //只会执行一次
    ,configureServer(server){
      console.log('configureServer');
      // console.log('configureServer server:', server);

      //默认↓这样 你的中间件的优先级会比vite内置的高
      //访问 http://localhost:3000/test 就会被拦截 并返回 'hello Vite Plugin'
      /*server.middlewares.use((req, res, next) => {
        if(req.url === '/test'){
          res.end('hello Vite Plugin')
        }else {
          next();
        }
      });*/

      //但如果你返回一个函数, 则会放在vite内置中间件的后面
      return ()=>{
        //你会返现仍然返回的是我们index.html的内容 而不是我们↓这里指定的
        server.middlewares.use((req, res, next) => {
          if(req.url === '/test'){
            res.end('hello Vite Plugin')
          }else {
            next();
          }
        });
      }
    }

    //一 npm run dev 就会执行↓
    //只会执行一次
    ,buildStart() {
      console.log('buildStart --- enforce:', enforce);
    }

    /** case4 */
    //修改html文件后 也会重新触发
    //热更新后会重新执行 因为我们会重新请求热更新的模块嘛
    ,transformIndexHtml(html){
      console.log('html:',html)
      return html.replace(`<div id="app"></div>`,`<div style="color:red">我在transformIndexHtml修改了html<div id="app"></div></div>`)
    }

    /** case5 */
    //当我们改变我们的源码时 就会触发↓的事件
    ,handleHotUpdate(ctx){
      console.log('handleHotUpdate--- --- ---');
      // console.log('handleHotUpdate ctx:',ctx);
      // console.log('ctx.file:',ctx.file);
      // console.log('ctx.timestamp:',ctx.timestamp);
      // console.log('ctx.modules:',ctx.modules);

      /*
      handleHotUpdate ctx: {
        file: 'F:/code/js_workplace/tutorial/vite_tutorial/11.插件开发/src/main.ts',
        timestamp: 1648786101848,
        modules: [
          ModuleNode {
            id: 'F:/code/js_workplace/tutorial/vite_tutorial/11.插件开发/src/main.ts',
            file: 'F:/code/js_workplace/tutorial/vite_tutorial/11.插件开发/src/main.ts',
            importers: Set(0) {},
            importedModules: Set(0) {},
            acceptedHmrDeps: Set(0) {},
            isSelfAccepting: false,
            transformResult: null,
            ssrTransformResult: null,
            ssrModule: null,
            lastHMRTimestamp: 0,
            url: '/src/main.ts',
            type: 'js',
            info: undefined
          }
        ],
        read: [Function: read],
        server: {
          config: {
            plugins: [Array],
            resolve: [Object],
            server: [Object],
            configFile: 'F:/code/js_workplace/tutorial/vite_tutorial/11.插件开发/vite.config.js',
            configFileDependencies: [Array],
            inlineConfig: [Object],
            root: 'F:/code/js_workplace/tutorial/vite_tutorial/11.插件开发',
            base: '/',
            publicDir: 'F:\\code\\js_workplace\\tutorial\\vite_tutorial\\11.插件开发\\public',
            cacheDir: 'F:\\code\\js_workplace\\tutorial\\vite_tutorial\\11.插件开发\\node_modules\\.vite',
            command: 'serve',
            mode: 'development',
            isProduction: false,
            build: [Object],
            preview: [Object],
            env: [Object],
            assetsInclude: [Function: assetsInclude],
            logger: [Object],
            packageCache: [Map],
            createResolver: [Function: createResolver],
            optimizeDeps: [Object],
            worker: [Object]
          },
          middlewares: [Function: app] {
            use: [Function: use],
            handle: [Function: handle],
            listen: [Function: listen],
            _events: undefined,
            _eventsCount: 0,
            _maxListeners: undefined,
            setMaxListeners: [Function: setMaxListeners],
            getMaxListeners: [Function: getMaxListeners],
            emit: [Function: emit],
            addListener: [Function: addListener],
            on: [Function: addListener],
            prependListener: [Function: prependListener],
            once: [Function: once],
            prependOnceListener: [Function: prependOnceListener],
            removeListener: [Function: removeListener],
            off: [Function: removeListener],
            removeAllListeners: [Function: removeAllListeners],
            listeners: [Function: listeners],
            rawListeners: [Function: rawListeners],
            listenerCount: [Function: listenerCount],
            eventNames: [Function: eventNames],
            route: '/',
            stack: [Array]
          },
          app: [Getter],
          httpServer: Server {
            maxHeaderSize: undefined,
            insecureHTTPParser: undefined,
            _events: [Object: null prototype],
            _eventsCount: 3,
            _maxListeners: undefined,
            _connections: 2,
            _handle: [TCP],
            _usingWorkers: false,
            _workers: [],
            _unref: false,
            allowHalfOpen: true,
            pauseOnConnect: false,
            httpAllowHalfOpen: false,
            timeout: 0,
            keepAliveTimeout: 5000,
            maxHeadersCount: null,
            headersTimeout: 60000,
            requestTimeout: 0,
            listen: [AsyncFunction (anonymous)],
            _connectionKey: '4:127.0.0.1:3000',
            [Symbol(IncomingMessage)]: [Function: IncomingMessage],
            [Symbol(ServerResponse)]: [Function: ServerResponse],
            [Symbol(kCapture)]: false,
            [Symbol(async_id_symbol)]: 43
          },
          watcher: FSWatcher {
            _events: [Object: null prototype],
            _eventsCount: 3,
            _maxListeners: undefined,
            _watched: [Map],
            _closers: [Map],
            _ignoredPaths: Set(0) {},
            _throttled: [Map],
            _symlinkPaths: Map(0) {},
            _streams: [Set],
            closed: false,
            _pendingUnlinks: Map(0) {},
            _emitReady: [Function (anonymous)],
            _emitRaw: [Function (anonymous)],
            _readyEmitted: true,
            options: [Object],
            _nodeFsHandler: [NodeFsHandler$1],
            _userIgnored: [Function (anonymous)],
            _readyCount: 17,
            _boundRemove: [Function: bound _remove],
            [Symbol(kCapture)]: false
          },
          pluginContainer: {
            options: [Object],
            getModuleInfo: [Function: getModuleInfo],
            buildStart: [AsyncFunction: buildStart],
            resolveId: [AsyncFunction: resolveId],
            load: [AsyncFunction: load],
            transform: [AsyncFunction: transform],
            close: [AsyncFunction: close]
          },
          ws: {
            on: [Function: bound addListener],
            off: [Function: bound removeListener],
            send: [Function: send],
            close: [Function: close]
          },
          moduleGraph: ModuleGraph {
            resolveId: [Function (anonymous)],
            urlToModuleMap: [Map],
            idToModuleMap: [Map],
            fileToModulesMap: [Map],
            safeModulesPath: [Set]
          },
          ssrTransform: [AsyncFunction: ssrTransform],
          transformWithEsbuild: [AsyncFunction: transformWithEsbuild],
          transformRequest: [Function: transformRequest],
          transformIndexHtml: [Function (anonymous)],
          ssrLoadModule: [Function: ssrLoadModule],
          ssrFixStacktrace: [Function: ssrFixStacktrace],
          listen: [Function: listen],
          close: [AsyncFunction: close],
          printUrls: [Function: printUrls],
          restart: [AsyncFunction: restart],
          _optimizeDepsMetadata: { hash: '74a98882', browserHash: 'ceab857b', optimized: {} },
          _ssrExternals: null,
          _globImporters: [Object: null prototype] {},
          _restartPromise: null,
          _forceOptimizeOnRestart: false,
          _isRunningOptimizer: false,
          _registerMissingImport: [Function: registerMissingImport],
          _pendingReload: null,
          _pendingRequests: Map(0) {}
        }
      }
      */

      // console.log('ctx.server:',ctx.server);
      ctx.server.ws.send({
        type: 'custom',
        event: 'test',
        data:{
          hello: 'world'
        }
      });
    }

    /** case1*/
    //当请求来了（请求资源）才会执行↓
    //热更新后会重新执行 因为我们会重新请求热更新的模块嘛
    ,resolveId(importee,importer){
      console.log('=resolveId=')
      /*console.log('resolveId --- enforce',enforce)
      console.log('importee:',importee);
      console.log('importer:',importer);*/

      //没有任何return 代表return的就是 undefined
      //表示在该插件中没有找到这个文件对应的地方
      //你要到其它的插件去找(调用其它插件的resolveId方法)
      //一旦有某个插件(你手动指定的 和 vite原生的) 在 resolveId中找到了
      //后续的插件的resolveId就不会再执行
      //而我们使用的大部分类型 都是已经在vite的核心插件里支持了的

      //参看 `11.插件开发のvite-vue3-jsx/index.js` 中 resolveId 的用法
    }

    //如果我们要加载的一个模块不是真实存在与硬盘上的就可以在这里自定义加载逻辑
    //热更新后会重新执行 因为我们会重新请求热更新的模块嘛
    ,load(){
      console.log('load --- enforce',enforce)

      //参看 参看 `11.插件开发のvite-vue3-jsx/index.js` 中 load 的用法
    }

    //热更新后会重新执行 因为我们会重新请求热更新的模块嘛
    ,transform(code, id, ssr) {
      console.log('transform--- --- ---');
    }
  }
};
